home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / tjgold.zip / INSTALL.001 / GOLDNDX.INC < prev    next >
Text File  |  1995-07-19  |  22KB  |  721 lines

  1. {--------------------------------------------------------------------------}
  2. {                Product: TechnoJock's Turbo Toolkit                       }
  3. {                Version: GOLD                                             }
  4. {                Build:   1.01                                             }
  5. {                                                                          }
  6. {  The index routines used in TTT Gold were developed by Dean Farwell II   }
  7. {  and are an adaptation of his excellent TBTREE database tools.           }
  8. {                                                                          }
  9. {                   Copyright 1988-1994 Dean Farwell II                    }
  10. {        Portions Copyright 1986-1995  TechnoJock Software, Inc.           }
  11. {                           All Rights Reserved                            }
  12. {                          Restricted by License                           }
  13. {--------------------------------------------------------------------------}
  14.  
  15.                      {********************************}
  16.                      {       Include: GOLDNDX         }
  17.                      {********************************}
  18.  
  19. const
  20.     NDXERROROFFSET = 2000;
  21.  
  22. type                       { keeps current info regarding search in progress }
  23.     FindRecord = Record
  24.         valid: Boolean;
  25.         partial: Boolean;
  26.         fieldNo: Integer;
  27.         vType:  ValueType;
  28.         lrNum: LrNumber;
  29.         findValue: ValueArray;
  30.         end;
  31.  
  32. var fRecord : FindRecord;
  33.     ndxUpperCaseFlag : Boolean;
  34.  
  35. procedure InitializeFindRecord;
  36.  
  37.     begin
  38.     with fRecord do
  39.         begin
  40.         valid := FALSE;
  41.         partial := FALSE;
  42.         fieldNo := 0;
  43.         vType := INVALIDVALUE;
  44.         lrNum := 0;
  45.         FillChar(findValue,SizeOf(findValue),0);
  46.         end;
  47.     end;
  48.  
  49.  
  50. procedure NdxInit;
  51.  
  52.     begin
  53.     InitializeFindRecord;
  54.     NdxSetUpperCase(TRUE);
  55.     NdxSetMaxPages(25);
  56.     end;
  57.  
  58.  
  59. function NdxErrorOccurred(NdxName : PathStr) : Boolean;
  60. { Checks for error which occurred accessing BTree routines
  61.   Releases all pages from buffer for file if error occured }
  62.  
  63.     begin
  64.     if BTreeErrorOccurred then
  65.         begin
  66.         DBSetError(GetBTreeError + NDXERROROFFSET);
  67.         NdxErrorOccurred := TRUE;
  68.         ReleaseAllPages(NdxName);
  69.         SetBTreeError(0);
  70.         end
  71.     else
  72.         NdxErrorOccurred := FALSE;
  73.     end;
  74.  
  75.  
  76. function GetValueType(fieldNo : Integer) : ValueType;
  77. {Returns the ValueType for the given field
  78.  
  79.           'C' --> STRINGVALUE
  80.           'L' --> BYTEVALUE
  81.           'D' --> LONGINTVALUE
  82.           'N' --> STRING (If Real)
  83.           'N' --> LONGINTVALUE (If Byte/Integer/Long Integer) }
  84.  
  85. var
  86.     fdType : Char;
  87.  
  88.     begin
  89.     fdType := DBGetFldType(fieldNo);
  90.     if fdType = 'C' then GetValueType := STRINGVALUE else
  91.     if fdType = 'L' then GetValueType := BYTEVALUE else
  92.     if fdType = 'D' then GetValueType := LONGINTVALUE else
  93.     if DbGetFldDec(fieldNo) = 0 then                          (* must be 'N' *)
  94.         GetValueType := LONGINTVALUE
  95.     else
  96.         GetValueType := STRINGVALUE;
  97.     end;
  98.  
  99.  
  100. function CalculateIndexFieldLength(fLength : Byte;
  101.                                    vType : ValueType) : VSizeType;
  102. { Returns The Field Length In Bytes For Each index Entry }
  103.  
  104. var
  105.     vSize : VSizeType;
  106.  
  107.     begin
  108.  
  109.     case vType of
  110.         STRINGVALUE  :
  111.             if (MaxNdxStrLen = 0) or (MaxNdxStrLen >= fLength + 1) then
  112.                 vSize := fLength + 1
  113.             else
  114.                 vSize := MaxNdxStrLen;
  115.         LONGINTVALUE : vSize := LONGINTSIZE;
  116.         BYTEVALUE    : vSize := BYTESIZE;
  117.         end;
  118.     CalculateIndexFieldLength := vSize;
  119.     end;
  120.  
  121.  
  122. procedure GetDBValue(lrNum : LrNumber;
  123.                      fieldNo : Integer;
  124.                      var dbValue);
  125.  
  126. var
  127.     dbStr : String absolute DBValue;
  128.     dbByte : Byte absolute DBValue;
  129.     dbLongInt : LongInt absolute DBValue;
  130.     dbDate : Dates absolute DBValue;
  131.     fdType : Char;
  132.  
  133.     begin
  134.     fdType := DBGetFldType(fieldNo);
  135.     case fdType of
  136.        'C': dbStr := DBGetFldString(lrNum,fieldNo);
  137.        'L': dbByte := Byte(DBGetFldLogical(lrNum,fieldNo));
  138.        'D': dbDate  := DBGetFldDate(lrNum,fieldNo);
  139.        'N': begin
  140.                if DbGetFldDec(fieldNo) = 0 then                      (* must be 'N' *)
  141.                   dbLongInt := DBGetFldLong(lrNum,fieldNo)
  142.                else
  143.                   dbStr := DBGetFldString(lrNum,fieldNo);
  144.             end;
  145.  
  146.     end;
  147. end;
  148.  
  149. function MeetsFindCriteria(var value2) : Boolean;
  150.  
  151. var
  152.     compareResult : Comparison;
  153.     tempStr1  : String;
  154.     tempStr2 : String absolute value2;
  155.  
  156.  
  157.     begin
  158.     CompareResult := CompareValues(fRecord.findValue,value2,fRecord.vType);
  159.  
  160.     if fRecord.partial then
  161.         begin
  162.         if fRecord.vType = STRINGVALUE then
  163.             begin
  164.             Move(fRecord.findValue,tempStr1,fRecord.findValue[1]+1);
  165.             if tempStr1 = Copy(tempStr2,1,Length(tempStr1)) then
  166.                 MeetsFindCriteria := TRUE
  167.             else
  168.                 MeetsFindCriteria := FALSE;
  169.             end
  170.         else
  171.             MeetsFindCriteria := FALSE;{not valid to do partial on
  172.                                         anything but strings}
  173.         end
  174.     else
  175.         MeetsFindCriteria := compareResult = EQUALTO;
  176.     end;
  177.  
  178.  
  179. function UpperCase(var str) : String;
  180.  
  181. { Returns Uppercase equivalent of a string.  Any characters in the string
  182.   other than 'a' .. 'z' are unaffected }
  183.  
  184. var
  185.     cnt : Byte;
  186.     oldStr : String absolute str;
  187.     newStr : String;
  188.     byteArr : Array [0 .. 255] of Char absolute NewStr;
  189.  
  190.     begin
  191.     newStr := oldStr;
  192.     for cnt := 1 to Length(oldStr) do
  193.         begin
  194.         byteArr[cnt] := UpCase(byteArr[cnt]);
  195.         end;
  196.     UpperCase := newStr;
  197.     end;
  198.  
  199.  
  200. procedure NdxBuild(FieldNo: integer; var DF : PathStr;
  201.                    fLength: Byte; FdType: Char);
  202. { Builds an index file.  Index can exist when this is called, but index
  203.   file must be CLOSED!!!  It creates or rewrites the index file, initializes
  204.   so that it is ready to accept values, and closes it}
  205.  
  206. var
  207.     lrNum : LrNumber;
  208.     vType : ValueType;
  209.     NdxAlias : File;
  210.     NdxName : PathStr;
  211.     eCode : Integer;
  212.  
  213. begin
  214.     with DbVars.ActiveNode^.DBInfo do
  215.         begin
  216.         IndexField := 0;
  217.         if NdxBuildNew(FieldNo) <> 0 then {error has been set already};
  218.         end;
  219.     end; { NdxBuild }
  220.  
  221.  
  222. function NdxBuildNew(FieldNo: integer): integer;
  223. { Builds an index file for the given field.  If index exists, the current index
  224.   deleted and replaced by the new index.  This routine can be called whether
  225.   index currently exists or not.  It can also be called with the same field as
  226.   is currently indexed.  In this latter case, it is the same as calling
  227.   RebuildIndex. }
  228.  
  229. var
  230.     vType : ValueType;
  231.     lrNum : LrNumber;
  232.     dbValue : ValueArray;
  233.     eCode : Integer;
  234.     NumRecs: longint;
  235.     upperStr : String;
  236. begin
  237.     NdxBuildNew := 1;  {assume error in case or early exit}
  238.     if (FieldNo < 1) or (FieldNo > DbTotalFields) then
  239.     begin
  240.        DBSetError(3001);
  241.        exit;
  242.     end;
  243.     with DbVars.ActiveNode^.DBInfo do
  244.     begin
  245.         if IndexField > 0 then                { check to see if index exists }
  246.         begin                           {clear the ndx field value buffer}
  247.            if NdxSpc <> nil then
  248.            begin
  249.               freemem(NdxSpc,NdxFldLen);
  250.               NdxSpc := nil;
  251.            end;
  252.         end
  253.         else
  254.         begin
  255.             NdxName := DbfName;
  256.             Delete(NdxName,Pos('.',DbfName),4);
  257.             NdxName := NdxName + IFX;
  258.             Assign(NdxAlias,NdxName);
  259.         end;
  260.  
  261.         ReleaseAllPages(NdxName);  (* Put here for safety to ensure buffer is
  262.                                       purged of any records from this index  *)
  263.         {$I-}
  264.         Rewrite(NdxAlias,PAGESIZE);
  265.         eCode := IOResult;
  266.         {$I+}
  267.         if eCode <> 0 then
  268.         begin
  269.            DBSetError(eCode + NDXERROROFFSET);
  270.            exit;
  271.         end;
  272.  
  273.         IndexField := FieldNo;
  274.         NdxFldLen := DBGetFldLength(IndexField);
  275.         vType := GetValueType(IndexField);
  276.  
  277.         CreateIndexFile(NdxName,
  278.                         NdxAlias,
  279.                         CalculateIndexFieldLength(NdxFldLen,vType),
  280.                         vType,
  281.                         FieldNo,
  282.                         ndxUpperCaseFlag);
  283.  
  284.         if NdxErrorOccurred(NdxName) then
  285.            exit;
  286.         SaveIndexFldValue := false;
  287.         IndexUpperCase := NdxUpperCaseFlag;
  288.         NumRecs := DbGetNumRecs;
  289.         DBVars.ShowNdxProgress(lrNum,NumRecs,0);
  290.         for lrNum := 1 to NumRecs do
  291.         begin
  292.             if DBRecordIsActive(lrNum) then
  293.             begin
  294.                 GetDBValue(lrNum,IndexField,dbValue);
  295.                 if (vType = STRINGVALUE) and indexUpperCase then
  296.                 begin
  297.                    upperStr := UpperCase(dbValue);
  298.                    InsertValueInBTree(NdxName,NdxAlias,lrNum,upperStr);
  299.                 end
  300.                 else
  301.                    InsertValueInBTree(NdxName,NdxAlias,lrNum,dbValue);
  302.                 if NdxErrorOccurred(NdxName) then
  303.                    exit;
  304.            end;
  305.            DBVars.ShowNdxProgress(lrNum,NumRecs,1);
  306.         end;
  307.         DBVars.ShowNdxProgress(lrNum,NumRecs,2);
  308.         SaveIndexFldValue := true;
  309.         NdxBuildNew := 0;
  310.    end;
  311. end; { NdxBuildNew }
  312.  
  313.  
  314. function NdxReBuild: integer;
  315. {  Rebuilds an EXISTING index file.  It rewrites the index file, initializes
  316.    so that it is ready to accept values, and sets the appropriate fields in
  317.    DBInfo record.  The file is left open.}
  318.  
  319.     begin
  320.     with DbVars.ActiveNode^.DBInfo do
  321.         NdxReBuild := NdxBuildNew(IndexField);    (* NdxBuildNew will do error handling    *)
  322.     end; { NdxReBuild }
  323.  
  324. procedure NdxAddKey;
  325. {Inserts value into index for the current indexed field for the current record.
  326.  Record and indexed field within record must be valid. }
  327.  
  328. var
  329.     lrNum : LrNumber;
  330.     dbValue : ValueArray;
  331.     upperStr : String;
  332.  
  333.     begin
  334.     with DbVars.ActiveNode^.DBInfo do
  335.         begin
  336.         lrNum := DbCurrRecNum;
  337.         GetDBValue(lrNum,IndexField,dbValue);
  338.         if (GetValueType(IndexField) = STRINGVALUE) and indexUpperCase then
  339.             begin
  340.             upperStr := UpperCase(dbValue);
  341.             InsertValueInBTree(NdxName,NdxAlias,lrNum,upperStr);
  342.             end
  343.         else
  344.             InsertValueInBTree(NdxName,NdxAlias,lrNum,dbValue);
  345.  
  346.         if NdxErrorOccurred(NdxName) then Exit;
  347.         end;
  348.     end; { NdxAddKey }
  349.  
  350. procedure NdxDelKey(RecNum : LongInt);
  351. {Deletes value from index for the indexed field within the current record. }
  352.  
  353. var
  354.     dbValue : ValueArray;
  355.     upperStr : String;
  356.  
  357.     begin
  358.     with DbVars.ActiveNode^.DBInfo do
  359.         begin
  360.         GetDBValue(RecNum,IndexField,dbValue);
  361.         if (GetValueType(IndexField) = STRINGVALUE) and indexUpperCase then
  362.             begin
  363.             upperStr := UpperCase(dbValue);
  364.             DeleteValueFromBTree(NdxName,NdxAlias,RecNum,upperStr);
  365.             end
  366.         else
  367.             DeleteValueFromBTree(NdxName,NdxAlias,RecNum,dbValue);
  368.  
  369.         if NdxErrorOccurred(NdxName) then Exit;
  370.         end;
  371.     end; { NdxDelKey }
  372.  
  373.  
  374. function DbFindFirst(FieldNo : integer;
  375.                      var FindValue;
  376.                      PartialMatch: boolean): LongInt;
  377. { Returns the record number for the first record in the index or in the file
  378.   which meets the given criteria.  If the FieldNo specified is the indexed
  379.   field, the index will be used.
  380.  
  381.   For anything but a string, it must be a perfect match.
  382.   A partail match is possible for strings if PartialMatch is TRUE.  In this
  383.   case, 'jone' is a partial match for 'jones'.
  384.  
  385.   Internal notes - If the index is used, the cursor is left on the entry past
  386.   the one returned.  This is to help alleviate problems if the entry at the
  387.   cursor is deleted. }
  388.  
  389. var
  390.     targetValue : ValueArray;
  391.     done : Boolean;
  392.     dummy : LrNumber;
  393.     upperStr : String;
  394.  
  395.     begin
  396.     fRecord.valid := TRUE;
  397.     fRecord.partial := PartialMatch;
  398.     fRecord.fieldNo := FieldNo;
  399.     fRecord.vType := GetValueType(FieldNo);
  400.  
  401.     with DbVars.ActiveNode^.DBInfo do
  402.         begin
  403.         if (fRecord.vType = STRINGVALUE) and indexUpperCase then
  404.             begin
  405.             upperStr := UpperCase(FindValue);
  406.             Move(upperStr,
  407.                  fRecord.findValue,
  408.                  CalculateIndexFieldLength(DBGetFldLength(FieldNo),
  409.                  fRecord.vType));
  410.             end
  411.         else
  412.             Move(FindValue,
  413.                  fRecord.findValue,
  414.                  CalculateIndexFieldLength(DBGetFldLength(FieldNo),
  415.                                            fRecord.vType));
  416.  
  417.         if fRecord.fieldNo = IndexField then
  418.             begin
  419.             fRecord.lrNum := UsingCursorAndGEValueGetLr(NdxName,
  420.                                                         NdxAlias,
  421.                                                         fRecord.findValue,
  422.                                                         fRecord.partial);
  423.             if NdxErrorOccurred(NdxName) then Exit;
  424.  
  425.             if fRecord.lrNum <> 0 then
  426.                 begin
  427.                 UsingCursorGetCurrValue(NdxName,NdxAlias,targetValue);
  428.                 if NdxErrorOccurred(NdxName) then Exit;
  429.                 if not MeetsFindCriteria(targetValue) then
  430.                     fRecord.lrNum := 0;
  431.                 dummy := UsingCursorGetNextLr(NdxName,NdxAlias);
  432.                 if NdxErrorOccurred(NdxName) then Exit;
  433.                 end;
  434.             end
  435.         else
  436.             begin            (* Index won't help .. look through entire file *)
  437.             fRecord.lrNum := 0;
  438.             done := (DBGetNumRecs < 1);
  439.             while not done do
  440.                 begin
  441.                 Inc(fRecord.lrNum);
  442.                 if DbRecordIsActive(fRecord.lrNum) then
  443.                     begin
  444.                     GetDBValue(fRecord.lrNum,FieldNo,targetValue);
  445.                     if MeetsFindCriteria(targetValue) then
  446.                         done := TRUE
  447.                     else
  448.                         if fRecord.lrNum >= DBGetNumRecs then
  449.                             begin
  450.                             done := TRUE;
  451.                             fRecord.lrNum := 0;
  452.                             end;
  453.                     end;
  454.                 end;
  455.             end;
  456.         end;
  457.     fRecord.valid := fRecord.lrNum <> 0;
  458.     DbFindFirst := fRecord.lrNum;
  459.     end; { DbFindFirst }
  460.  
  461.  
  462. function DBFindNext: Longint;
  463. {}
  464.  
  465. var
  466.     targetValue : ValueArray;
  467.     done : Boolean;
  468.     dummy : LrNumber;
  469.  
  470.     begin
  471.     if not fRecord.valid then
  472.         begin
  473.         DBFindNext := 0;
  474.         Exit;
  475.         end;
  476.  
  477.     with DbVars.ActiveNode^.DBInfo do
  478.         begin
  479.         if fRecord.fieldNo = IndexField then
  480.             begin
  481.             fRecord.lrNum := UsingCursorGetCurrLr(NdxName,NdxAlias);
  482.             if NdxErrorOccurred(NdxName) then Exit;
  483.  
  484.             if fRecord.lrNum <> 0 then
  485.                 begin
  486.                 UsingCursorGetCurrValue(NdxName,NdxAlias,targetValue);
  487.                 if NdxErrorOccurred(NdxName) then Exit;
  488.                 if not MeetsFindCriteria(targetValue) then
  489.                     fRecord.lrNum := 0;
  490.                 dummy := UsingCursorGetNextLr(NdxName,NdxAlias);
  491.                 if NdxErrorOccurred(NdxName) then Exit;
  492.                 end;
  493.             end
  494.         else
  495.             begin            (* Index won't help .. look through entire file *)
  496.             done := FALSE;
  497.             while not done do
  498.                 begin
  499.                 Inc(fRecord.lrNum);
  500.                 if DbRecordIsActive(fRecord.lrNum) then
  501.                     begin
  502.                     GetDBValue(fRecord.lrNum,fRecord.fieldNo,targetValue);
  503.                     if MeetsFindCriteria(targetValue) then
  504.                         done := TRUE
  505.                     else
  506.                         if fRecord.lrNum >= DBGetNumRecs then
  507.                             begin
  508.                             done := TRUE;
  509.                             fRecord.lrNum := 0;
  510.                             end;
  511.                     end;
  512.                 end;
  513.             end;
  514.         end;
  515.     fRecord.valid := fRecord.lrNum <> 0;
  516.     DbFindNext := fRecord.lrNum;
  517.     end; { DbFindNext }
  518.  
  519.  
  520. function NdxGotoFirst: longint;
  521. {}
  522.  
  523.     begin
  524.     fRecord.valid := TRUE;
  525.     fRecord.partial := FALSE;
  526.     fRecord.fieldNo := 0;
  527.  
  528.     with DbVars.ActiveNode^.DBInfo do
  529.         begin
  530.         fRecord.lrNum := UsingCursorGetFirstLr(NdxName,NdxAlias);
  531.         if NdxErrorOccurred(NdxName) then Exit;
  532.         NdxGotoFirst := fRecord.lrNum;
  533.         end;
  534.     end; { NdxGotoFirst }
  535.  
  536. function NdxGotoLast: longint;
  537. {}
  538.  
  539.     begin
  540.     fRecord.valid := TRUE;
  541.     fRecord.partial := FALSE;
  542.     fRecord.fieldNo := 0;
  543.  
  544.     with DbVars.ActiveNode^.DBInfo do
  545.         begin
  546.         fRecord.lrNum := UsingCursorGetLastLr(NdxName,
  547.                                               NdxAlias);
  548.         if NdxErrorOccurred(NdxName) then Exit;
  549.         NdxGotoLast := fRecord.lrNum;
  550.         end;
  551.     end; { NdxGotoLast }
  552.  
  553. function NdxGotoNext: longint;
  554. {}
  555.  
  556.     begin
  557.     fRecord.valid := TRUE;
  558.     fRecord.partial := FALSE;
  559.     fRecord.fieldNo := 0;
  560.  
  561.     with DbVars.ActiveNode^.DBInfo do
  562.         begin
  563.         fRecord.lrNum := UsingCursorGetNextLr(NdxName,
  564.                                               NdxAlias);
  565.         if NdxErrorOccurred(NdxName) then Exit;
  566.         NdxGotoNext := fRecord.lrNum;
  567.         end;
  568.     end; { NdxGotoNext }
  569.  
  570.  
  571. function NdxGotoPrev: longint;
  572. {}
  573.     begin
  574.     fRecord.valid := TRUE;
  575.     fRecord.partial := FALSE;
  576.     fRecord.fieldNo := 0;
  577.  
  578.     with DbVars.ActiveNode^.DBInfo do
  579.         begin
  580.         fRecord.lrNum := UsingCursorGetPrevLr(NdxName,NdxAlias);
  581.         if NdxErrorOccurred(NdxName) then Exit;
  582.         NdxGotoPrev := fRecord.lrNum;
  583.         end;
  584.     end; { NdxGotoPrev }
  585.  
  586.  
  587. function NdxGetRecNum(EntryNum : LongInt) : LongInt;
  588.  
  589.     begin
  590.     with DbVars.ActiveNode^.DBInfo do
  591.         begin
  592.         NdxGetRecNum := GetBTreeEntryLr(NdxName,NdxAlias,EntryNum);
  593.         if NdxErrorOccurred(NdxName) then Exit;
  594.         end;
  595.     end; { NdxGetRecNum }
  596.  
  597. function NdxValidate(Partial : Boolean): Byte;
  598. { This routine will perform a partial or a full validation of an index file.
  599.   (depending on the value of the variable Partial).  A partial check will
  600.   validate that the header record is intact and that the file structure
  601.   is valid.  A full validation will perform an additional check to ensure
  602.   that the data file and the index file are synchronized. The routine will
  603.   return one of the following values:
  604.  
  605.               0 : No errors
  606.              -1 : Header error
  607.              -2 : File error
  608.              -3 : Index and data files not synchronized }
  609. var
  610.     dbRecCnt,
  611.     lrNum : LrNumber;
  612.     compareResult : Comparison;
  613.     indexValue,
  614.     dBValue : ValueArray;
  615.     vType : ValueType;
  616.     result : Byte;
  617.  
  618.     begin
  619.     with DbVars.ActiveNode^.DBInfo do
  620.         begin
  621.         result := Byte(ValidateBTree(NdxName,NdxAlias));
  622.         if NdxErrorOccurred(NdxName) then Exit;
  623.  
  624.         if (result <> 0) or Partial then
  625.             begin
  626.             NdxValidate := result;
  627.             end
  628.         else
  629.             begin
  630.             vType := GetValueType(IndexField);
  631.             lrNum := UsingCursorGetFirstLr(NdxName,NdxAlias);
  632.             if NdxErrorOccurred(NdxName) then Exit;
  633.  
  634.             while lrNum <> 0 do
  635.                 begin
  636.                 UsingCursorGetCurrValue(NdxName,NdxAlias,indexValue);
  637.                 if NdxErrorOccurred(NdxName) then Exit;
  638.                 GetDBValue(lrNum,
  639.                            indexField,
  640.                            dbValue);
  641.                 compareResult := CompareValues(indexValue,dbValue,vType);
  642.                 if compareResult <> EQUALTO then
  643.                     begin
  644.                     NdxValidate := Byte(IFILEERROR);
  645.                     if NdxErrorOccurred(NdxName) then Exit;
  646.                     Exit;
  647.                     end;
  648.                 lrNum := UsingCursorGetNextLr(NdxName,NdxAlias);
  649.                 if NdxErrorOccurred(NdxName) then Exit;
  650.                 end;
  651.  
  652.             dbRecCnt := 0;
  653.             for lrNum := 1 to DBGetNumRecs do
  654.                 if DBRecordIsActive(lrNum) then
  655.                     Inc(dbRecCnt);
  656.  
  657.             if IndexEntryCount(NdxName,NdxAlias) = dbRecCnt then
  658.                 NdxValidate := Byte(NOERROR)
  659.             else
  660.                 NdxValidate := Byte(IFILEERROR);
  661.  
  662.             end;
  663.         end;
  664.     end; { NdxValidate }
  665.  
  666. procedure  NdxSetMaxPages(n : Word);
  667. { n must be 0 .. 1024 }
  668.     begin
  669.     SetMaxBufferPages(n);
  670.     end; { NdxSetPageSize }
  671.  
  672. procedure  NdxSetUpperCase(x : Boolean);
  673. { Set to TRUE if you want index entries to be converted to upper case and
  674.   FALSE otherwise.  If index entries are set to upper case, the index is
  675.   case insensitive }
  676.  
  677.     begin
  678.     ndxUpperCaseFlag := x;
  679.     end; { NdxSetUpperCase }
  680.  
  681. procedure NdxSetMaxStrLength(n : Byte);
  682. { if n > 0 and n < 245 then this routine will set the max index string size
  683.   to n.  This represents the maximum number of bytes that an index string
  684.   can occupy.  The number of characters would be one less. }
  685.  
  686.     begin
  687.     if n > MAXVALSIZE then
  688.         MaxNdxStrLen := MAXVALSIZE
  689.     else
  690.         if n > 0 then
  691.             MaxNdxStrLen := n;
  692.     end;
  693.  
  694. procedure NdxPrint;
  695.  
  696. var
  697.     lst : Text;
  698.  
  699.     begin
  700.     with DbVars.ActiveNode^.DBInfo do
  701.         begin
  702.         Assign(lst,'LPT1');
  703.         Rewrite(lst);
  704.         PrintBTreeInfo(NdxName,NdxAlias,FALSE,lst);
  705.         if NdxErrorOccurred(NdxName) then Exit;
  706.         end;
  707.     end;
  708.  
  709. function NdxCount : longint;
  710.  
  711.  
  712.     begin
  713.     with DbVars.ActiveNode^.DBInfo do
  714.         begin
  715.         NdxCount := IndexEntryCount(NdxName,NdxAlias);
  716.         if NdxErrorOccurred(NdxName) then Exit;
  717.         end;
  718.     end;
  719.  
  720.  
  721.